#ifndef VERTEXFORMAT_H
#define VERTEXFORMAT_H

#include "Exception.h"
#include "Log.h"
#include "ErrorHandlers.h"
#include "MemUtils.h"
#include "CommonTypes.h"

namespace Cvekas {

/// Helper for calculating Direct3D vertex formats
class VertexFormat
{
public:
	/// Default constructor
	VertexFormat();
	/// Constructor
	VertexFormat(bool position, uint uvs = 0, bool normal = false, bool binormal = false, 
		bool tangent = false, bool color = false);
	/// Destructor
	~VertexFormat();

	/// Returns true if format has position component. This should always be true.
	bool getPosition() const { return has_position; }
	/// Returns number of UV coordinates in format.
	uint getUVs() const { return number_of_uvs; }
	/// Returns true if format has normal component.
	bool getNormal() const { return has_normal; }
	/// Returns true if format has binormal component.
	bool getBinormal() const { return has_binormal; }
	/// Returns true if format has tangent component.
	bool getTangent() const { return has_tangent; }	
	/// Returns true if format has color component.
	bool getColor() const { return has_color; }

	/// Sets availibility of position component.
	bool setPosition(bool position) { has_position = position; needs_rebuild = true; }
	
	/// Sets number of UV coordinates
	int setUVs(int uvs) 
	{ 
		if(uvs >= 0 && uvs <= 8) 
		{ 
			number_of_uvs = uvs; 
			needs_rebuild = true; 
		} 
		else
		{ 
			throw EXCEPTION("Number of UVs must be between 0 and 8");
		}
	}

	/// Sets availibility of normal component.
	bool setNormal(bool normal) { has_normal = normal; needs_rebuild = true; }
	/// Sets availibility of binormal component.
	bool setBinormal(bool binormal) { has_binormal = binormal; needs_rebuild = true; }
	/// Sets availibility of tangent component.
	bool setTangent(bool tangent) { has_tangent = tangent; needs_rebuild = true; }
	/// Sets availibility of color component.
	bool setColor(bool color) { has_color = color; needs_rebuild = true; }
	
	/// Returns size in bytes of single vertex with this format.
	uint getSize() const;
	/// Returns number of elements in format.
	uint getNumberOfElements() const;
	/// Returns pointer to IDirect3DVertexDeclaration9
	IDirect3DVertexDeclaration9* getD3DVertexDeclaration(D3DDevicePtr device, uint stream);

private:
	bool has_position;
	uint number_of_uvs;
	bool has_normal;
	bool has_binormal;
	bool has_tangent;
	bool has_color;

	bool needs_rebuild;
	IDirect3DVertexDeclaration9* declaration;

	D3DDevicePtr last_device;
};

}

#endif